﻿using System;
using System.Xml.Linq;
using Nokia.PsuInterface;
using Nokia.SharpCore.DriverLoader;
using Nokia.SharpCore.Visa;

namespace Nokia.Psu
{
    public class PsuFactory : PluginBase
    {
        private XElement _configElement;
        private IVisa _visa;
        public IPsu Psu { get; private set; }

        public virtual IVisa Visa
        {
            get { return _visa ?? (_visa = new VisaFactory().CreateVisaDriver()); }
        }

        public override object CreateAndInitializeDriver(XElement configElement)
        {
            if (configElement == null) throw new ArgumentNullException("configElement");

            _configElement = configElement;
            // ReSharper disable once RedundantAssignment
            var address = PsuBase.GetAddressFromConfig(configElement);
            if (address == null)
                throw new ApplicationException("Could not get the driver address for Psu");

            var type = PsuBase.GetTypeFromConfig(configElement);
            if (type == null)
                throw new ApplicationException("Could not get the driver type for Psu");

            var identity = "";
            Psu = null;

            if (type.Equals("dummy", StringComparison.InvariantCultureIgnoreCase))
            {
                Psu = new PsuDummy();
            }
            else
            {
                Visa.OpenConnection(address);
                Visa.SetVisaTimeout(5000);
                identity = Visa.Query("*IDN?\n");
                Visa.Dispose();
                if (identity != null && identity.Contains("Agilent"))
                {
                    Psu = new PsuN5700();
                }
                // TODO Add proper Lambda comparison when tested against real instrument
                else if (identity != null && identity.Contains("LAMBDA"))
                {
                    Psu = new PsuLambda();
                }
            }

            if (Psu == null) throw new ApplicationException("Unknown Psu type: " + identity);

            Psu.Initialize(_configElement);

            return Psu;
        }

        public override Type ReturnInterfaceType()
        {
            return typeof(IPsu);
        }
    }
}